import java.util.*;
import java.io.*;


public class VisitorHelper{
	
	
	public static final String CLASS = "class";
	public static final String DEFINE = "define";
	public static final String ABSTRACTDEFINE = "abstractDefine";
	public static final String RELATIONSHIP = "relationship";
	public static final String ROLE = "role";
	public static final String PLAYER = "player";
	public static final String RELROLE = "relrole";
	//public static final String METHOD = "method";
	
	private HashMap<String, PowerTree> trees;
	private Vector<String> files; //per ora faccio così..
	
	public VisitorHelper(String fileName){
		trees = new HashMap();
		files= new Vector<String>();
		trees.put(fileName, new PowerTree());		
		
	}
	

	

	
	public void addNode(String file, String path, String name, String type){
		
		trees.get(file).addNode(path,name,type);		
	}
	
	public void addFile(String fileName){
		trees.put(fileName, new PowerTree());
		files.add(fileName);
	}
	
	public String getFrom(String file, String path, String rel){
		String returned = trees.get(file/*+".pj"*/).getFrom(path,rel);
		if(returned!=null) return returned;
		for(int i =0;i<files.size();i++){
			String iF = files.get(i);
			if(iF!=file){
				returned = trees.get(iF).getFrom(path,rel);			
				if(returned!=null) return returned;
			}
		}
		return null;
	}
	
		public String getTo(String file, String path, String rel){
		String returned = trees.get(file/*+".pj"*/).getTo(path,rel);
		if(returned!=null) return returned;
		for(int i =0;i<files.size();i++){
			String iF = files.get(i);
			if(iF!=file){
				returned = trees.get(iF).getTo(path,rel);			
				if(returned!=null) return returned;
			}
		}
		return null;
	}

	
	
	public String getPlayer(String file,String path, String role){
		String returned = trees.get(file/*+".pj"*/).getPlayer(path,role);
		if(returned!=null) return returned;
		for(int i =0;i<files.size();i++){
			String iF = files.get(i);
			if(iF!=file){
				returned = trees.get(iF).getPlayer(path,role);			
				if(returned!=null) return returned;
			}
		}
		return null;
	}
	
	public boolean is(String file, String path, String name,String type){
		Boolean returned = trees.get(file).is(path,name,type);		
		
		if(returned!=null) {
			
			return returned.booleanValue();
		}
		
		for(int i =0;i<files.size();i++){
			String iF = files.get(i);
			if(iF!=file){
				returned = trees.get(iF).is(path,name,type);			
				if(returned!=null) return returned.booleanValue();
			}
		}
		return false;
		
	}
	
	public String isFromOrTo(String file, String roleName){
		
		return trees.get(file).isFromOrTo(roleName);
	}
	
	
}


	
	


	class PowerTree{
		
		Vector<PowerNode> children;
		
		class PowerNode{
			
			String name;
			String type;
			Vector<PowerNode> children;
			
			PowerNode(String name, String type){
				this.name=name;
				this.type=type;
				children = new Vector<PowerNode>();
			}
			
			void setName(String name){
				this.name=name;
			}
			
			String getName(){
				return name;
			}
			
			void setType(String type){
				this.type=type;
			}
			
			String getType(){
				return type;
			}
			
			
			PowerNode getNode(String completeName){
				
				String name = firstName(completeName);
				if(getName().compareTo(name)!=0) return null;
				String last = lastNames(completeName);
				if(last.compareTo("")==0) return this;
				
				
				for(int i =0;i<children.size();i++){
					PowerNode next = children.get(i).getNode(last);
					if(next!=null) return next;
				}
				return null;	
			}

			
			
			
			void addNode(String path/*leggi scope*/, String name, String type){
				PowerNode newNode = new PowerNode(name, type);		
				if ("".compareTo(path)==0) {
					if(type.compareTo(VisitorHelper.RELROLE)==0){
						boolean hasFrom=false;
						//dovrei essere in una relazione
						for(int i =0;i<children.size();i++){
							if(children.get(i).type.compareTo("FROM")==0){
								hasFrom=true;
								break;
							}
						}
						if(hasFrom) type="TO";
						else type="FROM";					
						newNode = new PowerNode(name,type);
					}
					children.add(newNode);
					return;
				}			
				String nextStep;
				String nextPath;
				int firstDot = path.indexOf('.');
				if (firstDot<0){
					nextStep = path;
					nextPath ="";
				}
				else{
					nextStep = path.substring(0,firstDot);
					nextPath =path.substring(firstDot+1,path.length());
				}
				
				for (int i =0;i<children.size();i++){
					if(children.get(i).getName().compareTo(nextStep)==0){
						children.get(i).addNode(nextPath, name, type);
						return;
					}
				}
				throw new RuntimeException("No node with that name found");
				
			}
			


			String isFromOrTo(String roleName){
				if(type==VisitorHelper.RELATIONSHIP){
					if(getNodeFrom().compareTo(roleName)==0) return "From";
					if(getNodeTo().compareTo(roleName)==0) return "To";
					return null;//una relationship non può avere altri figli
				}
				else{
					for(PowerNode child : children){
						String r = child.isFromOrTo(roleName);
						if(r!=null) return r;			
					}	
				}
				return null;
				
			}
			
			String getNodePlayer(){		
				if (this.getType().compareTo("role")!=0) return null;		
				for(int i=0;i<children.size();i++){
					if(children.get(i).getType().compareTo("player")==0){
						return children.get(i).getName();
					}
				}
				return null;
			}
			
			String getNodeFrom(){
				if(this.getType().compareTo(VisitorHelper.RELATIONSHIP)!=0) return null;
				for(int i=0;i<children.size();i++){
					if(children.get(i).getType().compareTo("FROM")==0){
						return children.get(i).getName();
					}
				}
				return null;
			}
			
			String getNodeTo(){
				if(this.getType().compareTo(VisitorHelper.RELATIONSHIP)!=0) return null;
				for(int i=0;i<children.size();i++){
					if(children.get(i).getType().compareTo("TO")==0){
						return children.get(i).getName();
					}
				}
				return null;
			}

			
			Boolean is(String type){
				return new Boolean(this.getType().compareTo(type)==0);
			}
			
	}
		
		
		
			
		PowerTree(){
			children = new Vector<PowerNode>(); 
		}
		
		
		private String firstName(String path){
			String step;
			
			int firstDot = path.indexOf('.');
			if (firstDot<0){
				step = path;
			
			}
			else{
				step = path.substring(0,firstDot);
			
			}
			return step;
			
		}
		
		public String isFromOrTo( String roleName){
			for(PowerNode child : children){
				String r = child.isFromOrTo(roleName);
				if(r!=null) return r;
			}
			return null;
			
		}
		
		private String lastNames(String path){
			
			String nPath;
			int firstDot = path.indexOf('.');
			if (firstDot<0){				
				nPath ="";
			}
			else{
				
				nPath =path.substring(firstDot+1,path.length());
			}
			return nPath;
		}
		
		PowerNode getNode(String path, String name){
			//path è lo scope, dunque non necessario		
			for(int i =0;i<children.size();i++){
				PowerNode node = children.get(i).getNode(name);
				if(node!=null) return node;
			}
			String totalName = path+"."+name;
			for(int i =0;i<children.size();i++){
				PowerNode node = children.get(i).getNode(totalName);
				if(node!=null) return node;
			}			
			return null;
			
		}
		
		String getFrom(String path, String rel){
			PowerNode node = getNode(path,rel);
			if(node==null) return null;
			return node.getNodeFrom();
		}
		
		String getTo(String path, String rel){
			PowerNode node = getNode(path,rel);
			if(node==null) return null;
			return node.getNodeTo();
		}
		
		String getPlayer(String path, String roleName){			
			PowerNode node = getNode(path, roleName);
			if(node==null) return null;
			return node.getNodePlayer();
		}			
		
		
		Boolean is(String path, String name, String type){			
			PowerNode node = getNode(path,name);
			if (node==null) return null;
			
			return node.is(type);
		}
		
		void addNode(String path, String name, String type){
			if ("".compareTo(path)==0){
				
				children.add(new PowerNode(name,type));
				return;
			}			
			String nextStep;
			String nextPath;
			int firstDot = path.indexOf('.');
			if (firstDot<0){
				nextStep = path;
				nextPath ="";
			}
			else{
				nextStep = path.substring(0,firstDot);
				nextPath =path.substring(firstDot+1,path.length());
			}
			for (int i =0;i<children.size();i++){
				if(children.get(i).getName().compareTo(nextStep)==0){
					children.get(i).addNode(nextPath,name, type);
					return ;
				}
			}
			
			
		}
		
		
		
	}



